home *** CD-ROM | disk | FTP | other *** search
/ Ian & Stuart's Australian Mac: Not for Sale / Another.not.for.sale (Australia).iso / fade into you / getting there / Apps / MOO-1.7.6.src / src / vector.c < prev    next >
Text File  |  1994-11-02  |  28KB  |  918 lines

  1. /******************************************************************************
  2.   Copyright (c) 1992 Xerox Corporation.  All rights reserved.
  3.   Portions of this code were written by Stephen White, aka ghond.
  4.   Use and copying of this software and preparation of derivative works based
  5.   upon this software are permitted.  Any distribution of this software or
  6.   derivative works must comply with all applicable United States export
  7.   control laws.  This software is made available AS IS, and Xerox Corporation
  8.   makes no warranty about the software, its performance or its conformity to
  9.   any specification.  Any person obtaining a copy of this software is requested
  10.   to send their name and post office or electronic mail address to:
  11.     Pavel Curtis
  12.     Xerox PARC
  13.     3333 Coyote Hill Rd.
  14.     Palo Alto, CA 94304
  15.     Pavel@Xerox.Com
  16.  *****************************************************************************/
  17.  
  18. #include <ctype.h>
  19.  
  20. #include "my-string.h"
  21.  
  22. #include "config.h"
  23. #include "log.h"
  24. #include "storage.h"
  25. #include "utils.h"
  26. #include "vector.h"
  27.  
  28. enum var_len_type {VL_LABEL, VL_LITERAL, VL_VAR_NAME, VL_FORK};
  29.  
  30. typedef struct var_len_info *var_len_list; /* array */
  31.  
  32. typedef struct var_len_info { /* holds data for variable length */
  33.     enum var_len_type type;  /* data while create bytecodes */
  34.     unsigned where;         /* where value goes in unexpanded vector */
  35.     unsigned value;         /* value to possibly be expanded */
  36.     
  37.     /* these are used in mutating value field for labels */
  38.     unsigned num_prev_forks;     /* number of forks before value */
  39.     unsigned num_prev_literals;     /* number of literals before value */
  40.     unsigned num_prev_var_names; /* number of var names before value */
  41.     unsigned num_prev_labels;    /* number of labels before value*/
  42.     
  43.     struct var_len_info *next;     /* links used while generating  */
  44.     /* condition arms */
  45. } var_len_info;
  46.  
  47. unsigned num_var_names;            /* number of var names in program */
  48. unsigned num_forks;            /* number of forks in program */
  49. Var *literal_list;        /* array of literals in program */
  50. unsigned total_literals;    /* count of literal uses in program */
  51. unsigned num_literals;        /* number of unique literals in program */
  52. unsigned max_literal;        /* number of literals allocated */
  53.  
  54. struct local_env {
  55.     
  56.     var_len_list *vl_list;    /* pointer to array of literals */
  57.     unsigned top_vl_list;
  58.     unsigned max_vl_list;
  59.     
  60.     Byte *bytearray;        /* byte vector for this environment */
  61.     unsigned top_b;
  62.     unsigned max_b;
  63.     
  64.     int num_labels;        /* number of labels for current environment */
  65. };
  66.  
  67. Bytecodes ast2v(Stmt *, struct local_env *);
  68.  
  69. unsigned generate_stmt (Stmt *, struct local_env *);
  70. unsigned generate_expr (Expr *, struct local_env *);
  71. void fix_labels(Bytecodes *, struct local_env *);
  72.  
  73. #define HOW_MANY_BYTES(t)  (t <= 256 ? 1 : (t <= 256*256 ? 2 : 4))
  74. #define MAX(a, b)               ((a) > (b) ? (a) : (b))
  75. #define MAX3(a, b, c)           MAX(a, MAX(b, c))
  76. #define MAX4(a, b, c, d)    MAX(MAX(a, b), MAX(c, d))
  77.  
  78. static Bytecodes *return_forks; /* array */
  79. static struct local_env *fork_locals; /* array */
  80. static int num_return_forks;
  81.  
  82. void
  83. add_forked_vector(Bytecodes bc, struct local_env local)
  84. {
  85.     Bytecodes *new_forks =
  86.         (Bytecodes *)mymalloc(sizeof (Bytecodes) *
  87.           (num_return_forks+1), M_FORK_VECTORS);
  88.     struct local_env *new_fork_locals =
  89.         (struct local_env *)mymalloc(sizeof (struct local_env) *
  90.                     (num_return_forks+1), M_BYTECODE_INFO);
  91.     
  92.     if (return_forks != 0) {
  93.         int loop;
  94.         for (loop = 0; loop < num_return_forks; loop++) {
  95.             new_forks[loop] = return_forks[loop];
  96.             new_fork_locals[loop] = fork_locals[loop];
  97.         }
  98.         myfree(return_forks, M_FORK_VECTORS);
  99.         myfree(fork_locals, M_BYTECODE_INFO);
  100.     }
  101.     return_forks = new_forks;
  102.     fork_locals = new_fork_locals;
  103.     return_forks[num_return_forks] = bc;
  104.     fork_locals[num_return_forks++] = local;
  105. }
  106.  
  107. int
  108. vectorize(Stmt *stmt, Bytecodes *main_vector,
  109.       Bytecodes **fork_vectors,
  110.           Var **lit_list, unsigned *literal_list_size)
  111. {
  112.     Bytecodes   bc;
  113.     int loop;
  114.     struct local_env l_env;
  115.     
  116.     num_var_names = 0;
  117.     num_forks = 0;
  118.     
  119.     literal_list = 0;
  120.     total_literals = 0;
  121.     max_literal = 0;
  122.     num_literals = 0;
  123.     
  124.     return_forks = 0;
  125.     fork_locals = 0;
  126.     num_return_forks = 0;
  127.     
  128.     /* prepare to tree walk */
  129.     
  130.     /* tree walk */
  131.     bc = ast2v(stmt, &l_env);
  132.     
  133.     fix_labels(&bc, &l_env);
  134.     
  135.     if (fork_locals) {
  136.     for (loop = 0; loop < num_return_forks; loop++) {
  137.         fix_labels(&return_forks[loop], &fork_locals[loop]);
  138.     }
  139.     myfree(fork_locals, M_BYTECODE_INFO);
  140.     }
  141.     
  142.     if (num_literals < max_literal) {
  143.         Var *new_lits =
  144.         (Var *)mymalloc(sizeof(Var) * num_literals, M_LIT_LIST);
  145.     
  146.         if (literal_list != 0) {
  147.             int i;
  148.             for (i = 0; i < num_literals; i++)
  149.              new_lits[i] = literal_list[i];
  150.             myfree(literal_list, M_LIT_LIST);
  151.         }
  152.         literal_list = new_lits;
  153.         max_literal = num_literals;
  154.     }
  155.  
  156.     *main_vector = bc;
  157.     
  158.     *lit_list = literal_list;
  159.     *literal_list_size = num_literals;
  160.     
  161.     *fork_vectors = return_forks;
  162.     return num_return_forks;
  163. }
  164.  
  165. void 
  166. emit_byte(Byte what, struct local_env *l_env)
  167. {
  168.     int i;
  169.     if (l_env->top_b == l_env->max_b) {
  170.         int new_size = (l_env->bytearray == 0 ? 50 : 2 * l_env->max_b);
  171.         Byte *new_b = (Byte *) mymalloc(new_size, M_BYTECODES);
  172.     
  173.         if (l_env->bytearray != 0) {
  174.             for (i = 0; i < l_env->top_b; i++)
  175.                 new_b[i] = l_env->bytearray[i];
  176.             myfree(l_env->bytearray, M_BYTECODES);
  177.         }
  178.         l_env->max_b = new_size;    
  179.         l_env->bytearray = new_b;
  180.     }
  181.     l_env->bytearray[l_env->top_b++] = what;
  182. }
  183.  
  184. void
  185. emit_extended_byte(Byte what, struct local_env *l_env)
  186. {
  187.     emit_byte(OP_EXTENDED, l_env);
  188.     emit_byte(what, l_env);
  189. }
  190.  
  191. void
  192. free_vl_list(var_len_list *vl_list, int length)
  193. {
  194.     if (vl_list) {
  195.     int i;
  196.     for (i = 0; i < length; i++)
  197.         myfree(vl_list[i], M_VL_VALUE);
  198.     myfree(vl_list, M_VL_LIST);
  199.     }
  200. }
  201.  
  202. void
  203. fix_labels(Bytecodes *bc, struct local_env *l_env)
  204. {
  205.     int byte_loop, new_byte_index = 0, var_len_index = 0;
  206.     int value, size = 1, new_size;
  207.     Byte *new_bytes;
  208.     
  209.     bc->numbytes_fork = HOW_MANY_BYTES(num_forks);
  210.     bc->numbytes_literal = HOW_MANY_BYTES(num_literals);
  211.     bc->numbytes_var_name = HOW_MANY_BYTES(num_var_names);
  212.     
  213.     new_size = bc->size + (bc->numbytes_label  - 1) * bc->num_labels +
  214.                       (bc->numbytes_fork   - 1) * num_forks +
  215.                       (bc->numbytes_var_name - 1) * num_var_names +
  216.                   (bc->numbytes_literal - 1) * total_literals;
  217.     
  218.     new_bytes = (Byte *) mymalloc(new_size, M_BYTECODES);
  219.     
  220.     for (byte_loop = 0; byte_loop < bc->size; byte_loop++)
  221.         if (var_len_index < l_env->top_vl_list &&
  222.         byte_loop == l_env->vl_list[var_len_index]->where) {
  223.         
  224.         var_len_info *vl_info = l_env->vl_list[var_len_index];
  225.         
  226.             value = vl_info->value;
  227.             switch (vl_info->type) {
  228.               case VL_LABEL:
  229.               size = bc->numbytes_label;
  230.                value +=
  231.             vl_info->num_prev_forks * (bc->numbytes_fork-1) +
  232.             vl_info->num_prev_labels * (bc->numbytes_label-1) +
  233.             vl_info->num_prev_var_names * (bc->numbytes_var_name-1) +
  234.             vl_info->num_prev_literals * (bc->numbytes_literal-1);
  235.         break;
  236.           case VL_FORK:
  237.         size = bc->numbytes_fork;
  238.         break;
  239.           case VL_LITERAL:
  240.         size = bc->numbytes_literal;
  241.         break;
  242.           case VL_VAR_NAME:
  243.         size = bc->numbytes_var_name;
  244.         break;
  245.         }
  246.         if (size == 1)
  247.         new_bytes[new_byte_index] = value & 0377;
  248.         else {
  249.         if (size == 2) {
  250.             new_bytes[new_byte_index]   = (value >> 8) & 0377;
  251.             new_bytes[new_byte_index+1] =  value & 0377;
  252.         } else { /* numbytes == 4 */
  253.             new_bytes[new_byte_index]   = (value >> 24);
  254.             new_bytes[new_byte_index+1] = (value >> 16) & 0377;
  255.             new_bytes[new_byte_index+2] = (value >> 8) & 0377;
  256.             new_bytes[new_byte_index+3] =  value & 0377;
  257.         }
  258.         }
  259.         new_byte_index += size;
  260.         var_len_index++;
  261.     } else
  262.         new_bytes[new_byte_index++] = bc->vector[byte_loop];
  263.     
  264.     myfree(bc->vector, M_BYTECODES);
  265.     free_vl_list(l_env->vl_list, l_env->top_vl_list);
  266.     bc->vector = new_bytes;
  267.     bc->size = new_size;
  268. }
  269.  
  270. Bytecodes
  271. ast2v(Stmt *stmt, struct local_env *l_env)
  272. {
  273.     Bytecodes bc;
  274.     
  275.     l_env->top_vl_list = 0;
  276.     l_env->max_vl_list = 0;
  277.     l_env->vl_list = 0;
  278.     
  279.     l_env->top_b = 0;
  280.     l_env->max_b = 0;
  281.     l_env->bytearray = 0;
  282.     
  283.     l_env->num_labels = 0;
  284.     
  285.     bc.max_stack = generate_stmt(stmt, l_env);
  286.     
  287.     emit_byte(OP_DONE, l_env); /* append OP_DONE at the end */
  288.     
  289.     bc.size = l_env->top_b;
  290.     bc.vector = l_env->bytearray;
  291.     
  292.     if (bc.size <= 256)
  293.     bc.numbytes_label = 1;
  294.     else {
  295.     if (bc.size + l_env->num_labels > 256*256)
  296.         bc.numbytes_label = 4;
  297.     else
  298.         bc.numbytes_label = 2;
  299.     }
  300.     bc.num_labels = l_env->num_labels;
  301.     
  302.     return bc;
  303. }
  304.  
  305. unsigned
  306. continue_args(Arg_List *args, struct local_env *l_env)
  307. {
  308.     unsigned max_s, max_s1;
  309.     
  310.     if (args)
  311.     switch (args->kind) {
  312.       case ARG_NORMAL:
  313.         max_s = generate_expr(args->expr, l_env);
  314.         emit_byte(OP_LIST_ADD_TAIL, l_env);
  315.         max_s1 = continue_args(args->next, l_env);
  316.         return MAX(max_s, max_s1);
  317.         break;
  318.       case ARG_SPLICE:
  319.         max_s = generate_expr(args->expr, l_env);
  320.         emit_byte(OP_LIST_APPEND, l_env);
  321.         max_s1 = continue_args(args->next, l_env);
  322.         return MAX(max_s, max_s1);
  323.         break;
  324.     };
  325.     return 0;
  326. }
  327.  
  328. unsigned
  329. generate_arg_list(Arg_List *args, struct local_env *l_env)
  330. {
  331.     unsigned max_s, max_s1;
  332.     
  333.     if (args)
  334.     switch (args->kind) {
  335.       case ARG_NORMAL:
  336.         max_s = generate_expr(args->expr, l_env);
  337.         emit_byte(OP_MAKE_SINGLETON_LIST, l_env);
  338.         max_s1 = continue_args(args->next, l_env);
  339.         return MAX(max_s, 1 + max_s1);
  340.         break;
  341.       case ARG_SPLICE:
  342.         max_s = generate_expr(args->expr, l_env);
  343.         emit_byte(OP_CHECK_LIST_FOR_SPLICE, l_env);
  344.         max_s1 = continue_args(args->next, l_env);
  345.         return MAX(max_s, 1 + max_s1);
  346.         break;
  347.     }
  348.     else {
  349.         emit_byte(OP_MAKE_EMPTY_LIST, l_env);
  350.     return 1;
  351.     }
  352.     errlog("generate_arg_list didn't return a valid value!\n");
  353.     return -1;
  354. }
  355.  
  356. var_len_info *
  357. push_vl_info(enum var_len_type type, int where, int value,
  358.          var_len_info *v, struct local_env *l_env)
  359. {
  360.     var_len_info *vli;
  361.     
  362.     if (l_env->top_vl_list == l_env->max_vl_list) {
  363.         unsigned i, new_size =
  364.         l_env->max_vl_list ? 2 * l_env->max_vl_list : 50; 
  365.         var_len_list *new_vll =
  366.             mymalloc(sizeof(var_len_list) * new_size, M_VL_LIST);
  367.     
  368.     if (l_env->vl_list) {
  369.             for (i = 0; i < l_env->top_vl_list; i++)
  370.                 new_vll[i] = l_env->vl_list[i];
  371.             myfree(l_env->vl_list, M_VL_LIST);
  372.     }
  373.         l_env->max_vl_list = new_size;    
  374.         l_env->vl_list = new_vll;
  375.     }
  376.     
  377.     vli = l_env->vl_list[l_env->top_vl_list] =
  378.     mymalloc(sizeof(var_len_info), M_VL_VALUE);
  379.     if (v) {
  380.         *vli = *v;
  381.     vli->where = where;
  382.     } else {
  383.         vli->where = where;
  384.         vli->type = type;
  385.         vli->num_prev_forks = num_forks;
  386.         vli->num_prev_literals = num_literals;
  387.         vli->num_prev_var_names = num_var_names;
  388.         vli->num_prev_labels = l_env->num_labels;
  389.         vli->value = value;
  390.     }
  391.     l_env->top_vl_list++;
  392.     
  393.     emit_byte(value, l_env);
  394.     return vli;
  395. }
  396.  
  397. var_len_info *
  398. push_label(var_len_info *v, struct local_env *l_env)
  399. {
  400.     var_len_info *ret = push_vl_info(VL_LABEL, l_env->top_b, 128, v, l_env);
  401.     l_env->num_labels++;
  402.     return ret;
  403. }
  404.  
  405. void
  406. update_label(var_len_info *lab, struct local_env *l_env)
  407. {
  408.     lab->type = VL_LABEL;
  409.     lab->num_prev_forks = num_forks;
  410.     lab->num_prev_literals = num_literals;
  411.     lab->num_prev_var_names = num_var_names;
  412.     lab->num_prev_labels = l_env->num_labels;
  413.     lab->value = l_env->top_b;
  414. }
  415.  
  416. void
  417. push_literal(int slot, struct local_env *l_env)
  418. {
  419.     (void) push_vl_info(VL_LITERAL, l_env->top_b, slot, 0, l_env);
  420. }
  421.  
  422. void
  423. push_fork(Stmt *stmt, struct local_env *l_env)
  424. {
  425.     struct local_env forked_env;
  426.     Bytecodes bc;
  427.  
  428.     bc = ast2v(stmt, &forked_env);
  429.     add_forked_vector(bc, forked_env);
  430.     (void) push_vl_info(VL_FORK, l_env->top_b, num_forks++, 0, l_env);
  431. }
  432.  
  433. void
  434. push_var_name(int slot, struct local_env *l_env)
  435. {
  436.     (void) push_vl_info(VL_VAR_NAME, l_env->top_b, slot, 0, l_env);
  437.     num_var_names++;
  438. }
  439.  
  440. int
  441. get_lit_slot(Var v)
  442. {
  443.     int i;
  444.  
  445.     total_literals++;
  446.     for (i = 0; i < num_literals; i++)
  447.     if (v.type == TYPE_STR && literal_list[i].type == TYPE_STR) {
  448.         if (!strcmp(v.v.str, literal_list[i].v.str))
  449.         return i;
  450.     } else
  451.         if (equality(v, literal_list[i]))
  452.         return i;
  453.     
  454.     /* new literal */
  455.     
  456.     /* check if size of list needs to grow */
  457.     if (num_literals == max_literal) {
  458.     int new_size = (max_literal ? max_literal * 2 : 10);
  459.     Var *new_lits = (Var *)mymalloc(sizeof(Var) * new_size, M_LIT_LIST);
  460.     
  461.     if (literal_list != 0) {
  462.         for (i = 0; i < num_literals; i++)
  463.         new_lits[i] = literal_list[i];
  464.         myfree(literal_list, M_LIT_LIST);
  465.     }
  466.     max_literal = new_size;
  467.     literal_list = new_lits;
  468.     }
  469.     
  470.     literal_list[num_literals] = var_ref(v);
  471.     return num_literals++;
  472. }
  473.  
  474. void
  475. handle_variable(enum Opcode op, int slot, struct local_env *l_env)
  476. {
  477.     if (slot >= NUM_READY_VARS) {
  478.     emit_byte(op + NUM_READY_VARS, l_env);
  479.     push_var_name(slot, l_env);
  480.     } else 
  481.     emit_byte(op + slot, l_env);
  482. }
  483.  
  484. unsigned
  485. generate_ref_stack(Expr *stack, struct local_env *l_env, int *num_refs)
  486. {
  487.     int ans = 0;
  488.     unsigned max_s1, max_s2, max_s;
  489.    
  490.     switch (stack->kind) {
  491.       case EXPR_INDEX:
  492.     max_s1 = generate_ref_stack(stack->e.bin.lhs, l_env, &ans);
  493.     max_s2 = generate_expr(stack->e.bin.rhs, l_env);
  494.     emit_byte(OP_PUSH_REF, l_env);
  495.     max_s = max_s1 + max_s2 + 1;
  496.     /* max will sometime be greater than absolute minimum needed     */
  497.     /* if stack->e.bin.lhs has a max_stack > 3 for EXPR_PROP or      */
  498.     /* EXPR_INDEX, max_s will be larger than needed by a small       */
  499.     /* amount, but making the adjustment would cost more than it     */
  500.     /* would save.                            */
  501.     break;
  502.       case EXPR_PROP:
  503.     if (stack->e.bin.lhs->kind == EXPR_VAR && /* handle $prop case */
  504.         stack->e.bin.rhs->kind == EXPR_VAR &&
  505.         stack->e.bin.lhs->e.var.type == TYPE_OBJ &&
  506.         stack->e.bin.lhs->e.var.v.obj == 0)
  507.         (void) get_lit_slot(stack->e.bin.rhs->e.var);
  508.     max_s1 = generate_expr(stack->e.bin.lhs, l_env);
  509.     max_s2 = generate_expr(stack->e.bin.rhs, l_env);
  510.     emit_byte(OP_PUSH_GET_PROP, l_env);
  511.     max_s = MAX3(max_s1, 1 + max_s2, 3);
  512.     break;
  513.       default:
  514.     max_s = generate_expr(stack, l_env);
  515.     }
  516.     *num_refs = 1 + ans;
  517.     return max_s;
  518. }
  519.  
  520. void
  521. push_ref(Expr *e, struct local_env *l_env)
  522. {
  523.     switch(e->kind) {
  524.       case EXPR_PROP:
  525.     emit_byte(OP_PUT_PROP, l_env);
  526.     break;
  527.       case EXPR_INDEX:
  528.     push_ref(e->e.bin.lhs, l_env);
  529.     break;
  530.       case EXPR_ID:
  531.     handle_variable(OP_PUT, e->e.id.slot, l_env);
  532.     break;
  533.       default:
  534.     errlog("Illegal expression on lhs.");
  535.     }
  536. }
  537.  
  538. unsigned
  539. generate_expr(Expr *expr, struct local_env *l_env)
  540. {
  541.     int top_id, num_refs;
  542.     var_len_info *info1, *info2;
  543.     unsigned max_s1, max_s2, max_s3, max_s4;
  544.     
  545.     switch (expr->kind) {
  546.       case EXPR_VAR:
  547.     if (expr->e.var.type == TYPE_NUM &&
  548.         IN_OPTIM_NUM_RANGE(expr->e.var.v.num)) 
  549.         emit_byte(OPTIM_NUM_TO_OPCODE(expr->e.var.v.num), l_env);
  550.     else {
  551.         emit_byte(OP_IMM, l_env);
  552.         push_literal(get_lit_slot(expr->e.var), l_env); 
  553.     }
  554.     return 1;
  555.     break;
  556.       case EXPR_ID:
  557.     handle_variable(OP_PUSH, expr->e.id.slot, l_env);
  558.     return 1;
  559.     break;
  560.       case EXPR_PROP:
  561.     if (expr->e.bin.lhs->kind == EXPR_VAR && /* handle $prop case */
  562.         expr->e.bin.rhs->kind == EXPR_VAR &&
  563.         expr->e.bin.lhs->e.var.type == TYPE_OBJ &&
  564.         expr->e.bin.lhs->e.var.v.obj == 0)
  565.         (void) get_lit_slot(expr->e.bin.rhs->e.var);
  566.     max_s1 = generate_expr(expr->e.bin.lhs, l_env);
  567.     max_s2 = generate_expr(expr->e.bin.rhs, l_env);
  568.     emit_byte(OP_GET_PROP, l_env);
  569.     return MAX(max_s1, 1 + max_s2);
  570.     break;
  571.       case EXPR_VERB: 
  572.     max_s1 = generate_expr(expr->e.verb.obj, l_env);
  573.     if (expr->e.verb.verb->kind == EXPR_VAR && 
  574.         (expr->e.verb.verb->e.var.type == TYPE_STR &&
  575.          (isalpha(expr->e.verb.verb->e.var.v.str[0]) ||
  576.           expr->e.verb.verb->e.var.v.str[0] == '_'))) {
  577.         /* handle obj:vrb(args) */
  578.         emit_byte(OP_IMM, l_env);
  579.         top_id = l_env->top_vl_list;
  580.         push_literal(128, l_env);
  581.         max_s2 = 1;
  582.         max_s3 = generate_arg_list(expr->e.verb.args, l_env);
  583.         l_env->vl_list[top_id]->value =
  584.         get_lit_slot(expr->e.verb.verb->e.var);
  585.     } else {
  586.         max_s2 = generate_expr(expr->e.verb.verb, l_env);
  587.         max_s3 = generate_arg_list(expr->e.verb.args, l_env);
  588.     }
  589.     emit_byte(OP_CALL_VERB, l_env);
  590.     return MAX3(max_s1, 1 + max_s2, 2 + max_s3);
  591.     break;
  592.       case EXPR_INDEX:
  593.     max_s1 = generate_expr(expr->e.bin.lhs, l_env);
  594.     max_s2 = generate_expr(expr->e.bin.rhs, l_env);
  595.     emit_byte(OP_REF, l_env);
  596.     return MAX(max_s1, 1 + max_s2);
  597.     break;
  598.       case EXPR_RANGE:
  599.     max_s1 = generate_expr(expr->e.range.base, l_env);
  600.     max_s2 = generate_expr(expr->e.range.from, l_env);
  601.     max_s3 = generate_expr(expr->e.range.to, l_env);
  602.     emit_byte(OP_RANGE_REF, l_env);
  603.     return MAX3(max_s1, 1 + max_s2, 2 + max_s3);
  604.     break;
  605.       case EXPR_ASGN:
  606.     switch(expr->e.asgn.kind) {
  607.       case ASGN_VAR:
  608.         max_s1 = generate_expr(expr->e.asgn.value, l_env);
  609.         handle_variable(OP_PUT, expr->e.asgn.a.id.slot, l_env);
  610.         return max_s1;
  611.         break;
  612.       case ASGN_PROP:
  613.         /* to handle $prop case */
  614.         if (expr->e.asgn.a.bin.lhs->kind == EXPR_VAR &&
  615.         expr->e.asgn.a.bin.rhs->kind == EXPR_VAR &&
  616.         expr->e.asgn.a.bin.lhs->e.var.type == TYPE_OBJ &&
  617.         expr->e.asgn.a.bin.lhs->e.var.v.obj == 0)
  618.         (void) get_lit_slot(expr->e.asgn.a.bin.rhs->e.var);
  619.         max_s1 = generate_expr(expr->e.asgn.a.bin.lhs, l_env);
  620.         max_s2 = generate_expr(expr->e.asgn.a.bin.rhs, l_env);
  621.         max_s3 = generate_expr(expr->e.asgn.value, l_env);
  622.         emit_byte(OP_PUT_PROP, l_env);
  623.         return MAX3(max_s1, 1 + max_s2, 2 + max_s3);
  624.         break;
  625.       case ASGN_REF:
  626.         max_s1 = generate_ref_stack(expr->e.asgn.a.bin.lhs,
  627.                       l_env, &num_refs);
  628.         max_s2 = generate_expr(expr->e.asgn.a.bin.rhs, l_env);
  629.         max_s3 = generate_expr(expr->e.asgn.value, l_env);
  630.         emit_byte(OP_PUT_TEMP, l_env);
  631.         while (num_refs--)
  632.         emit_byte(OP_INDEXSET, l_env);
  633.         push_ref(expr->e.asgn.a.bin.lhs, l_env);
  634.         emit_byte(OP_POP, l_env);
  635.         emit_byte(OP_PUSH_TEMP, l_env);
  636.         return MAX(max_s1 + max_s2, max_s1 + 1 + max_s3);
  637.         break;
  638.       case ASGN_RANGE:
  639.         max_s1 = generate_ref_stack(expr->e.asgn.a.range.base, l_env,
  640.                     &num_refs);
  641.         max_s2 = generate_expr(expr->e.asgn.a.range.from, l_env);
  642.         max_s3 = generate_expr(expr->e.asgn.a.range.to, l_env);
  643.         max_s4 = generate_expr(expr->e.asgn.value, l_env);
  644.         emit_byte(OP_PUT_TEMP, l_env);
  645.         emit_extended_byte(OP_RANGESET, l_env);
  646.         while (--num_refs) /* subtract first here */
  647.         emit_byte(OP_INDEXSET, l_env);
  648.         push_ref(expr->e.asgn.a.range.base, l_env);
  649.         emit_byte(OP_POP, l_env);
  650.         emit_byte(OP_PUSH_TEMP, l_env);
  651.         return MAX3(max_s1 + max_s2, max_s1 + 1 + max_s3,
  652.             max_s1 + 2 + max_s4);
  653.         break;
  654.     }
  655.     break;
  656.       case EXPR_CALL:
  657.     max_s1 = generate_arg_list(expr->e.call.args, l_env);
  658.     emit_byte(OP_BI_FUNC_CALL, l_env);
  659.     emit_byte(expr->e.call.func, l_env);
  660.     return MAX(max_s1, 1);
  661.     break;
  662.       case EXPR_PLUS:
  663.       case EXPR_MINUS:
  664.       case EXPR_TIMES:
  665.       case EXPR_DIVIDE:
  666.       case EXPR_MOD:
  667.       case EXPR_EQ:
  668.       case EXPR_NE:
  669.       case EXPR_LT:
  670.       case EXPR_LE:
  671.       case EXPR_GT:
  672.       case EXPR_GE:
  673.       case EXPR_IN:
  674.     max_s1 = generate_expr(expr->e.bin.lhs, l_env);
  675.     max_s2 = generate_expr(expr->e.bin.rhs, l_env);
  676.     switch(expr->kind) {
  677.       case EXPR_PLUS: emit_byte(OP_ADD, l_env); break;
  678.       case EXPR_MINUS: emit_byte(OP_MINUS, l_env); break;
  679.       case EXPR_TIMES: emit_byte(OP_MULT, l_env); break;
  680.       case EXPR_DIVIDE: emit_byte(OP_DIV, l_env); break;
  681.       case EXPR_MOD: emit_byte(OP_MOD, l_env); break;
  682.       case EXPR_EQ: emit_byte(OP_EQ, l_env); break;
  683.       case EXPR_NE: emit_byte(OP_NE, l_env); break;
  684.       case EXPR_LT: emit_byte(OP_LT, l_env); break;
  685.       case EXPR_LE: emit_byte(OP_LE, l_env); break;
  686.       case EXPR_GT: emit_byte(OP_GT, l_env); break;
  687.       case EXPR_GE: emit_byte(OP_GE, l_env); break;
  688.       case EXPR_IN: emit_byte(OP_IN, l_env); break;
  689.       default: ;
  690.     }
  691.     return MAX(max_s1, 1 + max_s2);
  692.     break;
  693.       case EXPR_AND:
  694.       case EXPR_OR:
  695.     max_s1 = generate_expr(expr->e.bin.lhs, l_env);
  696.     switch(expr->kind) {
  697.       case EXPR_AND: 
  698.         emit_byte(OP_AND, l_env); 
  699.         break;
  700.       case EXPR_OR: 
  701.         emit_byte(OP_OR, l_env); 
  702.         break;
  703.       default: ;
  704.     }
  705.     info1 = push_label(0, l_env);
  706.     max_s2 = generate_expr(expr->e.bin.rhs, l_env);
  707.     update_label(info1, l_env);
  708.     return MAX(max_s1, max_s2);
  709.     break;
  710.       case EXPR_NEGATE:
  711.     max_s1 = generate_expr(expr->e.bin.lhs, l_env);
  712.     emit_byte(OP_UNARY_MINUS, l_env);
  713.     return max_s1;
  714.     break;
  715.       case EXPR_NOT:
  716.     max_s1 = generate_expr(expr->e.bin.lhs, l_env);
  717.     emit_byte(OP_NOT, l_env);
  718.     return max_s1;
  719.     break;
  720.       case EXPR_LIST:
  721.     return generate_arg_list(expr->e.list, l_env);
  722.     break;
  723.       case EXPR_COND:
  724.     max_s1 = generate_expr(expr->e.cond.condition, l_env);
  725.     emit_byte(OP_IF_QUES, l_env);
  726.     info1 = push_label(0, l_env);
  727.     max_s2 = generate_expr(expr->e.cond.consequent, l_env);
  728.     emit_byte(OP_JUMP, l_env);
  729.     info2 = push_label(0, l_env);
  730.     update_label(info1, l_env);
  731.     max_s3 = generate_expr(expr->e.cond.alternate, l_env);
  732.     update_label(info2, l_env);
  733.     return MAX3(max_s1, max_s2, max_s3);
  734.     break;
  735.       default: ;
  736.     }
  737.     return 0;
  738. }
  739.  
  740. var_len_info *
  741. generate_cond_arm(Cond_Arm *arm, Stmt *otherwise,
  742.           struct local_env *l_env, unsigned *max_s)
  743. {
  744.     var_len_info *info1, *info2;
  745.     unsigned max_s1, max_s2, max_s3 = 0;
  746.  
  747.     max_s1 = generate_expr(arm->condition, l_env);
  748.     emit_byte(OP_EIF, l_env);
  749.     info1 = push_label(0, l_env);    /* add label for else[if] part */
  750.     max_s2 = generate_stmt(arm->stmt, l_env);
  751.     emit_byte(OP_JUMP, l_env);  
  752.     info2 = push_label(0, l_env);    /* add label for COND exit */
  753.     update_label(info1, l_env);        /* fill in else[if] label */
  754.     if (arm->next) {
  755.     info1 = generate_cond_arm(arm->next, otherwise, l_env, &max_s3);
  756.     info2->next = info1;
  757.     *max_s = MAX3(max_s1, max_s2, max_s3);
  758.     return info2;
  759.     } else if (otherwise) 
  760.     max_s3 = generate_stmt(otherwise, l_env);
  761.     info2->next = 0;
  762.     *max_s = MAX3(max_s1, max_s2, max_s3);
  763.     return info2;
  764. }
  765.  
  766. unsigned
  767. generate_stmt(Stmt *s, struct local_env *l_env)
  768. {
  769.     Stmt *stmt = s;
  770.     var_len_info *info1, *info2;
  771.     var_len_info tmp;
  772.     unsigned stmt_list_max_s = 0, this_stmt_max_s, max_s1, max_s2, max_s3;
  773.  
  774.     while (stmt) {
  775.     this_stmt_max_s = 0;
  776.     switch (stmt->kind) {
  777.       case STMT_COND:
  778.         max_s1 = generate_expr(stmt->s.cond.arms->condition, l_env);
  779.         emit_byte(OP_IF, l_env);
  780.         info1 = push_label(0, l_env); /* add label for else[if] part */
  781.         max_s2 = generate_stmt(stmt->s.cond.arms->stmt, l_env);
  782.         emit_byte(OP_JUMP, l_env);
  783.         info2 = push_label(0, l_env); /* add label for COND exit */
  784.         update_label(info1, l_env);    /* fill in else[if] label */
  785.         info1 = 0;
  786.         max_s3 = 0;
  787.         if (stmt->s.cond.arms->next) {
  788.         info1 = generate_cond_arm(stmt->s.cond.arms->next,
  789.                       stmt->s.cond.otherwise,
  790.                       l_env, &max_s3);
  791.         } else if (stmt->s.cond.otherwise)
  792.         max_s3 = generate_stmt(stmt->s.cond.otherwise, l_env);
  793.         while (info1) {
  794.         update_label(info1, l_env);
  795.         info1 = info1->next;
  796.         }
  797.         update_label(info2, l_env);
  798.         this_stmt_max_s = MAX3(max_s1, max_s2, max_s3);
  799.         break;
  800.       case STMT_LIST:
  801.         max_s1 = generate_expr(stmt->s.list.expr, l_env);
  802.         /* add a constant 1 for some reason or other */
  803.         emit_byte(124, l_env); 
  804.         update_label(&tmp, l_env);
  805.         emit_byte(OP_FOR_LIST, l_env);
  806.         push_var_name(stmt->s.list.id.slot, l_env);
  807.         info1 = push_label(0, l_env);
  808.         max_s2 = generate_stmt(stmt->s.list.body, l_env);
  809.         emit_byte(OP_JUMP, l_env);
  810.         info2 = push_label(&tmp, l_env); /* add address of loop start */
  811.         update_label(info1, l_env);
  812.         this_stmt_max_s = MAX(max_s1, 2 + max_s2);
  813.         break;
  814.       case STMT_RANGE:
  815.         max_s1 = generate_expr(stmt->s.range.from, l_env);
  816.         max_s2 = generate_expr(stmt->s.range.to, l_env);
  817.         update_label(&tmp, l_env);
  818.         emit_byte(OP_FOR_RANGE, l_env);
  819.         push_var_name(stmt->s.range.id.slot, l_env);
  820.         info1 = push_label(0, l_env);
  821.         max_s3 = generate_stmt(stmt->s.range.body, l_env);
  822.         emit_byte(OP_JUMP, l_env);
  823.         info2 = push_label(&tmp, l_env);
  824.         update_label(info1, l_env);
  825.         this_stmt_max_s = MAX3(max_s1, 1 + max_s2, 2 + max_s3);
  826.         break;
  827.       case STMT_WHILE:
  828.         update_label(&tmp, l_env);
  829.         max_s1 = generate_expr(stmt->s.loop.condition, l_env);
  830.         emit_byte(OP_WHILE, l_env);
  831.         info1 = push_label(0, l_env); /* add exit from while loop */
  832.         max_s2 = generate_stmt(stmt->s.loop.body, l_env);
  833.         emit_byte(OP_JUMP, l_env);
  834.         info2 = push_label(&tmp, l_env);
  835.         update_label(info1, l_env);
  836.         this_stmt_max_s = MAX(max_s1, max_s2);
  837.         break;
  838.       case STMT_FORK:
  839.         max_s1 = generate_expr(stmt->s.fork.time, l_env);
  840.         if (stmt->s.fork.id.name == 0)
  841.         emit_byte(OP_FORK, l_env);
  842.         else
  843.         emit_byte(OP_FORK_WITH_ID, l_env);
  844.         push_fork(stmt->s.fork.body, l_env);
  845.         if (stmt->s.fork.id.name != 0)
  846.         push_var_name(stmt->s.fork.id.slot, l_env);
  847.         this_stmt_max_s = max_s1;
  848.         break;
  849.       case STMT_EXPR:
  850.         this_stmt_max_s = generate_expr(stmt->s.expr, l_env);
  851.         emit_byte(OP_POP, l_env);
  852.         break;
  853.       case STMT_RETURN:
  854.         if (!(stmt->s.expr)) {
  855.         emit_byte(OP_RETURN0, l_env);
  856.         this_stmt_max_s = 0;
  857.         } else {
  858.         this_stmt_max_s = generate_expr(stmt->s.expr, l_env);
  859.         emit_byte(OP_RETURN, l_env);
  860.         }
  861.         break;
  862.     }
  863.     stmt_list_max_s = MAX(stmt_list_max_s, this_stmt_max_s);
  864.     stmt = stmt->next;
  865.     }
  866.     return stmt_list_max_s;
  867. }
  868.  
  869. char rcsid_vector[] = "$Id: vector.c,v 1.13 1992/10/23 23:03:47 pavel Exp $";
  870.  
  871. /* $Log: vector.c,v $
  872.  * Revision 1.13  1992/10/23  23:03:47  pavel
  873.  * Added copyright notice.
  874.  *
  875.  * Revision 1.12  1992/10/23  22:23:32  pavel
  876.  * Eliminated all uses of the useless macro NULL.
  877.  *
  878.  * Revision 1.11  1992/10/21  03:02:35  pavel
  879.  * Converted to use new automatic configuration system.
  880.  *
  881.  * Revision 1.10  1992/10/17  20:58:01  pavel
  882.  * Global rename of strdup->str_dup, strref->str_ref, vardup->var_dup, and
  883.  * varref->var_ref.
  884.  *
  885.  * Revision 1.9  1992/09/24  02:38:46  pjames
  886.  * Fixed bug where number of unique literals in program was used to
  887.  * increase byte code size, instead of number of literals used in
  888.  * program.
  889.  *
  890.  * Revision 1.8  1992/08/28  23:16:40  pjames
  891.  * Added `emit_extended_byte()' for new opcodes.
  892.  * Added ASGN_RANGE code generation.
  893.  *
  894.  * Revision 1.7  1992/08/28  16:00:17  pjames
  895.  * Changed vardup to varref.
  896.  *
  897.  * Revision 1.6  1992/08/12  01:53:55  pjames
  898.  * EXPR_NEGATE case no longer needs to convert negative literals to
  899.  * optimized numbers, because they will be caught in EXPR_VAR.
  900.  *
  901.  * Revision 1.5  1992/08/10  16:26:24  pjames
  902.  * Updated #includes
  903.  *
  904.  * Revision 1.4  1992/07/30  21:26:08  pjames
  905.  * Added max_stack calculation (from parser.y).
  906.  *
  907.  * Revision 1.3  1992/07/27  18:26:19  pjames
  908.  * Change ct_env to var_names, const_env to literals, f_vectors to
  909.  * fork_vectors, removed global stack of local_ens. Improved readability
  910.  * of code.
  911.  *
  912.  * Revision 1.2  1992/07/21  00:08:03  pavel
  913.  * Added rcsid_<filename-root> declaration to hold the RCS ident. string.
  914.  *
  915.  * Revision 1.1  1992/07/20  23:23:12  pavel
  916.  * Initial RCS-controlled version.
  917.  */
  918.